The Idempotency HTTP Header Field
クライアントはランダムな値(UUID)などを、ヘッダ値をセットします。
サーバはこのIdempotency-Keyを元に複数回同じリクエストを受け取っても冪等処理を行います。2回目以降のリクエストに対しては、初回と同じレスポンスを返します。 サーバは一定期間後に受け取ったIdempotency-Keyの値を忘却しても問題ありません。
keyについて
code:syntax
The "Idempotency-Key" request header field describes
Idempotency-Key = idempotency-key-value
idempotency-key-value = opaque-value
opaque-value = DQUOTE *idempotencyvalue DQUOTE
idempotencyvalue = %x21 / %x23-7E / obs-text
; VCHAR except double quotes, plus obs-text
Clients MUST NOT include more than one "Idempotency-Key" header field
in the same request.
uniqueness
異なるリクエストペイロードには利用してはいけない
uniquenessの保証の仕方はリソースオーナが提示し、クライアントはそのとおりに実装しなければならない
UUIDを推奨する
validity expiry
time based idempotency key かもしれない
リソースサーバはexpiryに関するポリシーを予め表明すべき
idempotency fingerprint
idempotencyフィンガープリントは、リクエストの一意性を決定するために idempotencyキーと組み合わせて使用してもよい
idempotencyフィンガープリントはリソースの実装によって生成される
idempotencyフィンガープリント生成アルゴリズムは、フィンガープリントを生成するために、以下のいずれかまたは類似のアプローチを使用してもよい
リクエスト・ペイロード全体のチェックサム
リクエストペイロード内の選択された要素のチェックサム
リクエスト ペイロード内の各フィールドのフィールド値の一致
リクエストペイロード内の選択された要素のフィールド値の一致
リクエスト・ダイジェスト/署名
Idempotency Enforcement Scenarios
サーバで未知のkeyが来たとき
通常通りエンドポイントの処理する
既知のkeyが来たとき
Retry
最初のリクエストが完了したあとにretryリクエストが来た場合、既に完了したリクエストと同一のレスポンスを返す
Concurrent Request
最初のリクエストが完了する前にretryリクエストが来た場合、サーバはresource conflict errorを返す
Error Scenarios
Idempotency-Key headerが要求されるエンドポイントでheaderが送られなかった場合
status code 400を返す
リンクを添える
code:response
HTTP/1.1 400 Bad Request
rel="describedby"; type="text/html"
異なるリクエストペイロードでidempotency keyが再利用された場合
code:response
HTTP/1.1 422 Unprocessable Entity
rel="describedby"; type="text/html"
期限切れのidempotency keyが再利用された場合 draft v01 からは削除された
code:response
HTTP/1.1 422 Unprocessable Entity
rel="describedby"; type="text/html"
最初のリクエストが完了する前にreplayリクエストが来た場合
code:response
HTTP/1.1 409 Conflict
rel="describedby"; type="text/html"
それ以外のエラー
validation errorとか
適切に処理する
既存の実装
Organization: Stripe
Description: Stripe uses custom HTTP header named "Idempotency-Key"
Organization: Adyen
Description: Adyen uses custom HTTP header named "Idempotency-Key"
Organization: Dwolla
Description: Dwolla uses custom HTTP header named "Idempotency-Key"
Organization: Interledger
Description: Interledger uses custom HTTP header named "Idempotency-Key"
Organization: WorldPay
Description: WorldPay uses custom HTTP header named "Idempotency-Key"
Organization: Yandex
Description: Yandex uses custom HTTP header named "Idempotency-Key"
コンセプトの実装
Organization: Django
Description: Django uses custom HTTP header named "HTTP_IDEMPOTENCY_KEY"
Organization: Twilio
Description: Twilio uses custom HTTP header named "I-Twilio-Idempotency-Token" in webhooks
Organization: PayPal
Description: PayPal uses custom HTTP header named "PayPal-Request-Id"
Organization: RazorPay
Description: RazorPay uses custom HTTP header named "X-Payout-Idempotency"
Organization: OpenBanking
Description: OpenBanking uses custom HTTP header called "x-idempotency-key"
Organization: Square
Description: To make an idempotent API call, Square recommends adding a property named "idempotency_key" with a unique value in the request body.
Organization: Google Standard Payments
Description: Google Standard Payments API uses a property named "requestId" in request body in order to provider idempotency in various use cases.
Organization: BBVA
Description: BBVA Open Platform uses custom HTTP header called "X-Unique-Transaction-ID"
Organization: WebEngage
Description: WebEngage uses custom HTTP header called "x-request-id" to identify webhook POST requests uniquely to achieve events idempotency.
Security consideration
リソースサーバはidempotency keyのフォーマットを公開し、リクエスト処理前に検証を行うべき